﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Useful.GUI.HierarchyDataGridView;
using Useful.MVP2;

namespace FileDuplicateRemover.Gui
{
    public partial class DuplicateListViewForm : Form, IDuplicateListView
    {
        private readonly BindingSource bsDataSource = new BindingSource();
        private string _GroupedByName;

        internal DuplicateListViewPresenter Presenter { get; set; }

        public DuplicateListViewForm()
        {
            InitializeComponent();

            Presenter = new DuplicateListViewPresenter(this, null, new MyPresenterImpl());
        }

        public event EventHandler<ExceptionEventArgs> ExceptionRaised;
        public event EventHandler<EventArgs> ViewLoaded;
        public event EventHandler<EventArgs> ViewClosed;
        public event EventHandler<EventArgs> RefreshClicked;
        public event EventHandler<EventArgs> AddClicked;
        public event EventHandler<EventArgs> EditClicked;
        public event EventHandler<EventArgs> DeleteClicked;
        public event EventHandler<EventArgs> CurrentItemPositionChanged;
        public event EventHandler<InitListViewEventArgs> ViewInited;
        public event EventHandler<EventArgs> CollapseClicked;
        public event EventHandler<EventArgs> CheckItemClicked;
        public event EventHandler<EventArgs> CheckNotFirstClicked;
        public event EventHandler<EventArgs> UnCheckAllClicked;
        public event EventHandler<EventArgs> BeforeDirectorySelected;
        public event EventHandler<EventArgs> AfterDirectorySelected;
        public event EventHandler<EventArgs> DeleteCheckedClicked;
        public event EventHandler<FormClosingEventArgs> FormClosingEvent;
        public event EventHandler<EventArgs> BreakProgressClicked;
        public event EventHandler<EventArgs> FileNameClicked;
        public event EventHandler<EventArgs> FormShown;
        public event EventHandler<BoolEventArgs> HideEmptyClicked;
        public event EventHandler<EventArgs> TimerProgressTick;
        public event EventHandler<EventArgs> CreateDirectoryTreeClicked;
        public event EventHandler<EventArgs> CalcHashClicked;
        public event EventHandler<StringEventArgscs> LoadViewModelClicked;
        public event EventHandler<StringEventArgscs> SaveViewModelClicked;

        public string SelectedDataFileFullName { get; set; }

        public string SelectedRootDirectory
        {
            get
            {
                return tbSelectedDirectory.Text;
            }
            set
            {
                tbSelectedDirectory.Text = value;
            }
        }

        public string InfoText
        {
            get
            {
                return lInfo.Text;
            }
            set
            {
                lInfo.Text = value;
            }
        }

        public object ListDataSource
        {
            get
            {
                return bsDataSource.DataSource;
            }
            set
            {
                bsDataSource.DataSource = value;

                ResizeAndSort();
            }
        }

        public bool EnableWorkWithGrid
        {
            set
            {
                bCollapseAll.Enabled = value;
                bCheckNotFirst.Enabled = value;
                bUncheckAll.Enabled = value;
                cbHideEmpty.Enabled = value;

                свернутьразвернутьToolStripMenuItem.Enabled = value;
                отметитьНЕПервыеToolStripMenuItem.Enabled = value;
                снятьОтметкуToolStripMenuItem.Enabled = value;
                скрытьПустыеToolStripMenuItem.Enabled = value;
            }
        }

        public bool EnableWorkWithFormButtons
        {
            set
            {
                bClose.Enabled = value;
                bSearchDuplicate.Enabled = value;
                bSelectDirectory.Enabled = value;
                bCreateDirectoryTree.Enabled = value;
                bCalcHash.Enabled = value;

                выходToolStripMenuItem.Enabled = value;
                поискДубликатовToolStripMenuItem.Enabled = value;
                выборПапкиToolStripMenuItem1.Enabled = value;
                анализToolStripMenuItem.Enabled = value;
                вычислениеХэшейToolStripMenuItem.Enabled = value;

                loadListToolStripMenuItem.Enabled = value;
                сохранитЬсписокToolStripMenuItem.Enabled = value;
            }
        }

        public bool EnableDeleteChecked
        {
            get
            {
                return bDeleteChecked.Enabled;
            }
            set
            {
                bDeleteChecked.Enabled = value;
                удалитьОтмеченныеToolStripMenuItem.Enabled = value;
            }
        }

        public bool EnableActionBreakButton
        {
            get
            {
                return tssbActionBreak.Enabled;
            }
            set
            {
                tssbActionBreak.Enabled = value;
                прерватьToolStripMenuItem.Enabled = value;
            }
        }

        public object GetCurrentItem()
        {
            return gridData.CurrentRow != null ? gridData.CurrentRow.DataBoundItem : null;
        }

        public bool EnableView
        {
            get
            {
                return bSearchDuplicate.Enabled;
            }
            set
            {
                bSearchDuplicate.Enabled = value;
                поискДубликатовToolStripMenuItem.Enabled = value;
            }
        }

        public bool EnableAdd
        {
            get
            {
                return false;
            }
            set
            {
            }
        }

        public bool EnableEdit
        {
            get
            {
                return false;
            }
            set
            {
            }
        }

        public bool EnableDelete
        {
            get
            {
                return bDeleteChecked.Enabled;
            }
            set
            {
                bDeleteChecked.Enabled = value;
                удалитьОтмеченныеToolStripMenuItem.Enabled = value;
            }
        }

        public void Init(object repository, bool allowView, bool allowAdd, bool allowEdit, bool allowDelete)
        {
            ViewInited(this, new InitListViewEventArgs(repository, allowView, allowAdd, allowEdit, allowDelete));
        }

        private void bClose_Click(object sender, EventArgs e)
        {
            ViewClosed(this, EventArgs.Empty);
        }

        private void DuplicateListViewForm_Load(object sender, EventArgs e)
        {
            try
            {
                if (!DesignMode)
                {
                    InitGrid();
                    SetActionProgressWidth();

                    ViewLoaded(this, EventArgs.Empty);
                }
            }
            catch(Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("DuplicateListViewForm_Load", ex));   
            }
        }

        private void bCollapseAll_Click(object sender, EventArgs e)
        {
            CollapseClicked(this, EventArgs.Empty);
        }

        private void bDeleteChecked_Click(object sender, EventArgs e)
        {
            DeleteChecked();
        }

        private void DeleteChecked()
        {
            try
            {
                gridData.SuspendLayout();

                DeleteCheckedClicked(this, EventArgs.Empty);

                gridData.ResumeLayout();
                gridData.Refresh();
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("bDeleteChecked_Click", ex));
            }
        }

        private void bSearchDuplicate_Click(object sender, EventArgs e)
        {
            SearchDuplicate();
        }

        private void SearchDuplicate()
        {
            try
            {
                RefreshClicked(this, EventArgs.Empty);

                //ResizeAndSort();
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("bSearchDuplicate_Click", ex));
            }
        }

        private void ResizeAndSort()
        {
            gridData.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);

            if (bsDataSource.DataSource != null)
            {
                gridData.Sort(gridData.Columns["Length"], ListSortDirection.Descending);
            }
        }

        private DataGridViewImageColumn _cImageType;
        private DataGridViewImageColumn _cImageDeleted;
        private DataGridViewLinkColumn _cLinkName;

        private void InitGrid()
        {
            gridData.AllowUserToAddRows = false;
            gridData.MultiSelect = false;
            gridData.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            gridData.ReadOnly = false;
            gridData.AutoGenerateColumns = false;
            gridData.ShowContextMenu = cmsMenu;
            gridData.SetCurrentCellByRightMouseClick = true;

            gridData.CreateColumns(typeof(GridItem));
            gridData.Columns["Checked"].ReadOnly = false;

            _cImageType = new DataGridViewImageColumn();
            _cImageType.Name = "ItemTypeColumn";
            _cImageType.HeaderText = "Тип";
            _cImageType.DisplayIndex = 0;
            _cImageType.Width = 30;
            _cImageType.Resizable = DataGridViewTriState.False;
            _cImageType.DefaultCellStyle.NullValue = null;
            _cImageType.ImageLayout = DataGridViewImageCellLayout.Zoom;
            gridData.Columns.Add(_cImageType);

            _cImageDeleted = new DataGridViewImageColumn();
            _cImageDeleted.Name = "ItemDeletedColumn";
            _cImageDeleted.HeaderText = "Удалён";
            _cImageDeleted.DisplayIndex = gridData.Columns["Result"].DisplayIndex;
            _cImageDeleted.Width = 30;
            _cImageDeleted.Resizable = DataGridViewTriState.False;
            _cImageDeleted.DefaultCellStyle.NullValue = null;
            _cImageDeleted.ImageLayout = DataGridViewImageCellLayout.Zoom;
            gridData.Columns.Add(_cImageDeleted);

            _cLinkName = new DataGridViewLinkColumn();
            _cLinkName.Name = "LinkNameColumn";
            _cLinkName.HeaderText = "Имя";
            _cLinkName.DataPropertyName = "Name";
            _cLinkName.DisplayIndex = gridData.Columns["Name"].DisplayIndex;
            gridData.Columns.Add(_cLinkName);

            gridData.Columns["Name"].Visible = false;

            gridData.SetAutoSizeColumnsMode(DataGridViewAutoSizeColumnMode.None);
            gridData.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
            gridData.SetColumnsSortMode(DataGridViewColumnSortMode.Automatic);

            gridData.DataSource = bsDataSource;

            gridData.ProcessCellFormatting += gridData_ProcessCellFormatting;
            gridData.Sorted += gridData_Sorted;
            gridData.CurrentCellDirtyStateChanged += gridData_CurrentCellDirtyStateChanged;
            gridData.CellContentClick += gridData_CellContentClick;
            gridData.KeyUp += gridData_KeyUp;
        }

        private void gridData_KeyUp(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Space && gridData.CurrentRow != null)
                {
                    GridItem item = (GridItem) GetCurrentItem();
                    item.Checked = !item.Checked;

                    CheckItemClicked(this, EventArgs.Empty);

                    gridData.Refresh();
                }
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("gridData_KeyUp", ex));
            }
        }

        private void gridData_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.RowIndex > -1 && e.ColumnIndex > -1)
                {
                    if (gridData.Columns[e.ColumnIndex] == _cLinkName)
                    {
                        FileNameClicked(this, EventArgs.Empty);
                    }
                }
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("gridData_CellContentClick", ex));
            }
        }

        private void gridData_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            gridData.CommitEdit(DataGridViewDataErrorContexts.Commit);

            CheckItemClicked(this, EventArgs.Empty);
        }

        private void gridData_Sorted(object sender, EventArgs e)
        {
            GroupBy(_GroupedByName);
        }

        private Font _DeletedItemFont = null;
        private Font GetDeletedItemFont(Font font)
        {
            if (_DeletedItemFont == null)
            {
                _DeletedItemFont = new Font(font, FontStyle.Italic);
            }

            return _DeletedItemFont;
        }

        private void gridData_ProcessCellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            GridItem item = gridData.GetDataRow<GridItem>(e.RowIndex);

            //if(item.IsFirst)
            //{
            //    e.CellStyle.BackColor = Color.Pink;
            //}

            if (gridData.Rows[e.RowIndex].HeaderCell is RowHeaderCell)
            {
                RowHeaderCell headerCell = (RowHeaderCell) gridData.Rows[e.RowIndex].HeaderCell;

                if (headerCell.IsGroupHeader)
                {
                    e.CellStyle.BackColor = Color.Pink;
                }
            }

            if(item.IsDeleted)
            {
                e.CellStyle.ForeColor = Color.DarkGray;
                e.CellStyle.Font = GetDeletedItemFont(e.CellStyle.Font);
            }

            if(gridData.Columns[e.ColumnIndex] == _cImageType)
            {
                e.Value = item.IsDirectory ? Properties.Resources.Folder : null;
            }

            if (gridData.Columns[e.ColumnIndex] == _cImageDeleted)
            {
                e.Value = item.IsDeleted ? Properties.Resources.Deleted : null;
            }
        }

        private void bSelectDirectory_Click(object sender, EventArgs e)
        {
            SelectDirectory();
        }

        private void SelectDirectory()
        {
            try
            {
                BeforeDirectorySelected(this, EventArgs.Empty);

                FolderBrowserDialog fbd = new FolderBrowserDialog();

                fbd.SelectedPath = SelectedRootDirectory;

                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    SelectedRootDirectory = fbd.SelectedPath;

                    AfterDirectorySelected(this, EventArgs.Empty);
                }
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("Выбор директории", ex));
            }
        }

        private void gridData_CurrentCellChanged(object sender, EventArgs e)
        {
            CurrentItemPositionChanged(this, EventArgs.Empty);
        }

        public void Collapse(bool hide)
        {
            try
            {
                gridData.CollapseFirstGroup(!hide);
            }
            catch(Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("Collapse", ex));
            }
        }

        public void GroupBy(string name)
        {
            try
            {
                _GroupedByName = name;

                if (bsDataSource.DataSource != null)
                {
                    if (!String.IsNullOrEmpty(_GroupedByName))
                        gridData.GroupRows(_GroupedByName);
                    //else
                    //    gridData.UnGroupRows();
                }
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("GroupBy", ex));
            }
        }

        private void bCheckFirst_Click(object sender, EventArgs e)
        {
            CheckFirst();
        }

        private void CheckFirst()
        {
            try
            {
                gridData.SuspendLayout();

                CheckNotFirstClicked(this, EventArgs.Empty);

                gridData.ResumeLayout();
                gridData.Refresh();
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("bCheckFirst_Click", ex));
            }
        }

        private void bUncheckFirst_Click(object sender, EventArgs e)
        {
            UncheckFirst();
        }

        private void UncheckFirst()
        {
            try
            {
                gridData.SuspendLayout();

                UnCheckAllClicked(this, EventArgs.Empty);

                gridData.ResumeLayout();
                gridData.Refresh();
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("bUncheckFirst_Click", ex));
            }
        }

        private void удалитьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteClicked(this, EventArgs.Empty);
            gridData.Refresh();
        }

        public void SetActionProgesssCurrentVal(int val)
        {
            try
            {
                tspbActionProgtress.Value = val;
            }
            catch (Exception ex)
            {
                throw;
            }


            gridData.Refresh();
            //System.Threading.Thread.Sleep(50);
        }

        public int MaximumProgressValue
        {
            get
            {
                return tspbActionProgtress.Maximum;
            }
            set
            {
                tspbActionProgtress.Maximum = value;
            }
        }

        private void DuplicateListViewForm_SizeChanged(object sender, EventArgs e)
        {
            try
            {
                SetActionProgressWidth();
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("DuplicateListViewForm_SizeChanged", ex));
            }
        }

        private void SetActionProgressWidth()
        {
            tspbActionProgtress.Width = this.Width - 200;
            this.Refresh();
        }

        private void DuplicateListViewForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            FormClosingEvent(this, e);
        }

        private void tssbActionBreak_ButtonClick(object sender, EventArgs e)
        {
            BreakProgressClicked(this, EventArgs.Empty);
        }

        public string ActionHeader
        {
            get
            {
                return tsslActionHeader.Text;
            }
            set
            {
                tsslActionHeader.Text = value;
                SetActionProgressWidth();
            }
        }

        private void DuplicateListViewForm_Shown(object sender, EventArgs e)
        {
            FormShown(this, EventArgs.Empty);
        }

        private void cbHideEmpty_CheckedChanged(object sender, EventArgs e)
        {
            HideEmptyCore(cbHideEmpty.Checked);
        }

        private void HideEmptyCore(bool val)
        {
            try
            {
                gridData.CurrentCell = null;

                gridData.SuspendLayout();

                HideEmptyClicked(this, new BoolEventArgs(val));

                gridData.ResumeLayout();
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("cbHideEmpty_CheckedChanged", ex));
            }
        }

        public bool HideEmpty
        {
            get
            {
                return cbHideEmpty.Checked;
            }
            set
            {
                cbHideEmpty.Checked = value;
                скрытьПустыеToolStripMenuItem.Checked = value;
            }
        }

        public void RowVisible(GridItem item, bool visible)
        {
            int ind = bsDataSource.IndexOf(item);

            if (ind != -1)
                gridData.Rows[ind].Visible = visible;
        }

        public bool EnableTimerProgress
        {
            get
            {
                return timerProgress.Enabled;
            }
            set
            {
                timerProgress.Enabled = value;
            }
        }

        private void timerProgress_Tick(object sender, EventArgs e)
        {
            try
            {
                TimerProgressTick(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("timerProgress_Tick", ex));
            }
        }

        private void bCreateDirectoryTree_Click(object sender, EventArgs e)
        {
            CreateDirectoryTree();
        }

        private void CreateDirectoryTree()
        {
            try
            {
                CreateDirectoryTreeClicked(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("Построение дева директорий", ex));
            }
        }

        public bool EnableCreateTree
        {
            get
            {
                return bCreateDirectoryTree.Enabled;
            }
            set
            {
                bCreateDirectoryTree.Enabled = value;
                анализToolStripMenuItem.Enabled = value;
            }
        }

        public bool EnableCalcHash
        {
            get
            {
                return bCalcHash.Enabled;
            }
            set
            {
                bCalcHash.Enabled = value;
                вычислениеХэшейToolStripMenuItem.Enabled = value;
            }
        }

        public bool EnableSelectDirectory
        {
            get
            {
                return bSelectDirectory.Enabled;
            }
            set
            {
                bSelectDirectory.Enabled = value;
            }
        }

        public bool EnableSearchDuplicate
        {
            get
            {
                return bSearchDuplicate.Enabled;
            }
            set
            {
                bSearchDuplicate.Enabled = value;
                поискДубликатовToolStripMenuItem.Enabled = value;
            }
        }

        private void выходToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ViewClosed(this, EventArgs.Empty);
        }

        private void выборПапкиToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            SelectDirectory();
        }

        private void анализToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateDirectoryTree();
        }

        private void поискДубликатовToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SearchDuplicate();
        }

        private void свернутьразвернутьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CollapseClicked(this, EventArgs.Empty);
        }

        private void отметитьНЕПервыеToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CheckFirst();
        }

        private void снятьОтметкуToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UncheckFirst();
        }

        private void удалитьОтмеченныеToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteChecked();
        }

        private void скрытьПустыеToolStripMenuItem_Click(object sender, EventArgs e)
        {
            HideEmptyCore(скрытьПустыеToolStripMenuItem.Checked);
        }

        private void прерватьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            BreakProgressClicked(this, EventArgs.Empty);
        }

        private string GetSaveFullFilename()
        {
            SaveFileDialog fd = new SaveFileDialog();

            fd.FileName = SelectedDataFileFullName;
            fd.DefaultExt = "xml";
            fd.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*";

            if (fd.ShowDialog() == DialogResult.OK)
            {
                return fd.FileName;
            }
            else
                return null;
        }

        private string GetOpenFullFilename()
        {
            OpenFileDialog fd = new OpenFileDialog();

            //fd.InitialDirectory = 
            fd.FileName = SelectedDataFileFullName;
            fd.DefaultExt = "xml";
            fd.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*";

            if (fd.ShowDialog() == DialogResult.OK)
            {
                return fd.FileName;
            }
            else
                return null;
        }

        private void loadListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                LoadViewModelClicked(this, new StringEventArgscs(GetOpenFullFilename()));
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("loadListToolStripMenuItem_Click", ex));
            }
        }

        private void сохранитЬсписокToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                SaveViewModelClicked(this, new StringEventArgscs(GetSaveFullFilename()));
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("сохранитЬсписокToolStripMenuItem_Click", ex));
            }
        }

        private void bCalcHash_Click(object sender, EventArgs e)
        {
            CalcHash();
        }

        private void CalcHash()
        {
            try
            {
                CalcHashClicked(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                ExceptionRaised(this, new ExceptionEventArgs("CalcHash", ex));
            }
        }

        private void вычислениеХэшейToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CalcHash();
        }
    }
}
